package com.chengyi.serialport.demo.activity

import android.text.InputType
import android.widget.TextView
import androidx.databinding.ObservableField
import com.chengyi.serialboard.sdk.CYSerialboard
import com.chengyi.serialboard.sdk.RyPcbLockSerialPortUtil
import com.chengyi.serialboard.sdk.SerialPortOptions
import com.chengyi.serialport.demo.R
import com.chengyi.serialport.demo.databinding.ActivityRyPcbLockDemoBinding
import com.chengyi.serialport.demo.utils.ExpirableFunction2
import com.hjq.toast.Toaster
import com.wyj.utils.QMUIDialogHelper
import me.goldze.mvvmhabit.binding.command.BindingAction

class ActivityRyPcbLockDemo : BaseActivity<ActivityRyPcbLockDemoBinding, ActivityRyPcbLockDemo.ViewModel>() {

    override fun getLayoutRes(): Int = R.layout.activity_ry_pcb_lock_demo
    override fun initViews() {
        initBar(binding.myTopBar)
    }

    class ViewModel : BaseSerialPortViewModel<RyPcbLockSerialPortUtil>() {
        override val serialportPath = ObservableField("/dev/ttyS4")
        override val baudrate = ObservableField("115200")
        override val textHex: TextView?
            get() = uiChangeLiveData.getBinding<ActivityRyPcbLockDemoBinding>()?.textHex
        private val readLockCallback = ExpirableFunction2<Int, List<Int>>(2000)
        private val openLockCallback = ExpirableFunction2<Int, List<Int>>(2000)
        private val relayCallback = ExpirableFunction2<Int, Boolean>(2000)
        val terminalId = ObservableField("")
        val version = ObservableField("")

        override fun createSerialPortUtil(path: String, baudrate: Int): RyPcbLockSerialPortUtil? {
            val options = SerialPortOptions().path(path).baudrate(baudrate)
            return RyPcbLockSerialPortUtil(options, CYSerialboard.getRyPcbLockKey() ?: "", object : RyPcbLockSerialPortUtil.Callback {
                override fun onSendHexCallback(sendHex: String?) {
                    sendHex?.let(this@ViewModel::onSerialPortSendCallback)
                }

                override fun onReceiveHexCallback(receiveHex: String?) {
                    receiveHex?.let(this@ViewModel::onSerialPortReceiveCallback)
                }

                override fun onRelayCallback(relayNum: Int, success: Boolean) {
                    relayCallback.getUnExpired().forEach {
                        it.invoke(relayNum, success)
                    }
                }

                override fun onOpenLockCallback(lockCount: Int, lockStatusList: List<Int>) {
                    openLockCallback.getUnExpired().forEach {
                        it.invoke(lockCount, lockStatusList)
                    }
                }

                override fun onReadLockCallback(lockCount: Int, lockStatusList: List<Int>) {
                    readLockCallback.getUnExpired().forEach {
                        it.invoke(lockCount, lockStatusList)
                    }
                }

                override fun onHeartCallback(lockCount: Int, lockStatusList: List<Int>) {
                    onReadHeartCallback(lockCount, lockStatusList)
                }

                override fun onTerminalIdCallback(terminalId: String?, version: String?) {
                    this@ViewModel.terminalId.set(terminalId)
                    this@ViewModel.version.set(version)
                }
            })
        }

        fun onReadHeartCallback(lockCount: Int, lockStatusList: List<Int>) {
            val sb = StringBuilder()
            for (i in 0 until lockCount) {
                sb.append("锁${i + 1}：${if (lockStatusList[i] == 1) "开" else "关"}")
                if (i < lockCount - 1) {
                    sb.append("，")
                }
            }
            onSerialPortAnalysisCallback(sb.toString())
        }

        val onReadClick = BindingAction {
            runSerialPortCommand {
                readLockCallback.set { lockCount, lockStatusList ->
                    onReadHeartCallback(lockCount, lockStatusList)
                    true
                }
                it.readLockInfo()
            }
        }

        fun getOnOpenCloseLockDialogClick(status: Int) = BindingAction {
            QMUIDialogHelper.createEditDialog(uiChangeLiveData.getActivity() ?: return@BindingAction, "锁号", InputType.TYPE_CLASS_NUMBER, "请输入", onEditListener = object : QMUIDialogHelper.OnEditListener {
                override fun onEditListener(text: String) {
                    val lockNum = text.toIntOrNull()
                    if (lockNum == null) {
                        Toaster.show("请输入正确的锁号")
                        return
                    }
                    getOnOpenCloseLockClick(lockNum, status).call()
                }
            }).show()
        }

        fun getOnOpenCloseLockClick(lockNum: Int, status: Int) = BindingAction {
            runSerialPortCommand {
                openLockCallback.add { _: Int, lockStatusList: List<Int> ->
                    val lockStatus = lockStatusList.getOrNull(status)
                    if (lockStatus == null) {
                        onSerialPortAnalysisCallback("锁${lockNum}：状态未知")
                    } else {
                        onSerialPortAnalysisCallback("锁${lockNum}：${if (lockStatus == 1) "开" else "关"}")
                    }
                    true
                }
                val func = if (status == 1) it::openLock else it::closeLock
                func.invoke(lockNum.toByte())
            }
        }

        fun getOnOpenCloseRelayClick(relayNum: Int, status: Int) = BindingAction {
            runSerialPortCommand {
                relayCallback.add { mRelayNum: Int, success: Boolean ->
                    if (mRelayNum == relayNum) {
                        onSerialPortAnalysisCallback("继电器${mRelayNum}${if (status == 1) "开启" else "关闭"}${if (success) "成功" else "失败"}")
                        true
                    } else {
                        false
                    }
                }
                val func = if (status == 1) it::openRelay else it::closeRelay
                func.invoke(relayNum.toByte())
            }
        }

        override fun onSerialPortClosed() {
        }
    }
}